/* MultiSelectWidget.js
 *
 * Copyright 2006, Tim Dwelle.
 *
 * Licensed under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in
 * compliance with the License.  You may obtain a copy of
 * the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the License is
 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 * CONDITIONS OF ANY KIND, either express or implied.  See
 * the License for the specific language governing
 * permissions and limitations under the License.
 *
 */

$package("dowry.widget");

/**
 * Object represenation of a UI widget that knows how to
 * handle multi-select boxes.
 *
 */
$class("MultiSelectWidget").$extends("SelectWidget").$as(
{
    /**
     * Gets the value of the bound element, represented as a
     * type appropriate for the element's datatype.
     *
     * <p>
     * This works conceptually identical to SelectWidget's
     * <code>getValue()</code>, except that it will return
     * an array of values.
     * </p>
     *
     * @return  the value
     *
     */
    getValue : function()
    {
        var val = null;

        var ele = this.getElement();
        if (ele)
        {
            for (var i=0; i < ele.length; i++)
            {
                var opt = ele.options[i];
                if (opt.selected)
                {
                    // get actual value
                    var optVal = opt.value;

                    // if it is a select with read-only
                    // prompts, then treat as if it was null
                    if (opt.prompt)
                    {
                        optVal = null;
                    }

                    // convert empty strings to null
                    else if (optVal == "")
                    {
                        optVal = null;
                    }

                    // try to lookup value from values map
                    else if (this._values[optVal] != null)
                    {
                        optVal = this._values[optVal];
                    }

                    // set new value into array
                    if (optVal != null)
                    {
                        // don't populate array until we find
                        // our first value
                        if (val == null)
                        {
                            val = new Array();
                        }

                        val[val.length] = optVal;
                    }
                }
            }
        }

        // convert the raw value
        var dt = this.getDatatype();
        if (dt)
        {
            val = dt.toDatatype(val);
        }

        return val;
    },

    /**
     * Sets the value of the bound element, using a type
     * appropriate for the element's datatype.
     *
     * <p>
     * This works conceptually identical to SelectWidget's
     * <code>setValue()</code>, except that it can takes
     * in an array of values.
     * </p>
     *
     * @param vals  the value to set
     *
     */
    setValue : function(vals)
    {
        // if they haven't passed us an array,
        // assume its an array of 1 item
        if (vals == null || !vals.join)
        {
            vals = [ vals ];
        }

        // convert the raw value
        var dt = this.getDatatype();
        if (dt)
        {
            vals = dt.toFormattedString(vals);
        }

        var ele = this.getElement();
        if (ele)
        {
            // clear any existing selections...
            for (var i = 0; i < ele.options.length; i++)
            {
                var opt = ele.options[i];
                opt.selected = false;
            }

            // loop through all our values
            if (vals != null)
            {
                for (var i=0; i < vals.length; i++)
                {
                    var val = vals[i];

                    // can't have a select option
                    // with a null value... use an
                    // empty string instead
                    if (val == null)
                    {
                        val = "";
                    }

                    // don't de-select... only select... since
                    // we already cleared all the existing
                    // selections on the last pass
                    for (var j = 0; j < ele.options.length; j++)
                    {
                        var opt = ele.options[j];
                        if (opt.value == val)
                        {
                            opt.selected = true;
                        }
                    }
                }
            }
        }
    }
});